/**************************************************************
 *   File:	ScreenQuad.cpp
 * Author:	Andrew Thorpe
 *  Brief:	A base class for all on screen elements
 **************************************************************/
#include "StdAfx.h"
#include "ScreenQuad.h"
#include "Texture.h"

using namespace Fossil;
ScreenQuad::ScreenQuad(void)
: m_X(0.0f)
, m_Y(0.0f)
, m_Width(1.0f)
, m_Height(1.0f)
, m_pParent(0)
, m_pFirstChild(0)
, m_pNextSibling(0)
, m_pTexture(0)
{
	m_pTexture = Texture::Create("./background1.png");
}

ScreenQuad::~ScreenQuad(void)
{
	m_pParent = 0;
	m_pFirstChild = 0;
	m_pNextSibling = 0;

	//TextureManager will delete
	m_pTexture = 0;
}

void ScreenQuad::Render(float width, float height, float depth) const
{
	float x = width * m_X;
	float y = height * m_Y;
	float w = width * m_Width;
	float h = height * m_Height;

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, m_pTexture->Handle());

	glBegin(GL_QUADS);

	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(x,     y,     depth);

	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(x,     y + h, depth);

	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(x + w, y + h, depth);

	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(x + w, y    , depth);

	glEnd();

}

ScreenQuad* ScreenQuad::AttachChild(ScreenQuad* pScreenQuad)
{
	pScreenQuad->AttachScreenQuadToParent(this);
	return pScreenQuad; 
}


bool ScreenQuad::IsAncestorOf(ScreenQuad* pScreenQuad)
{
	while(0 != pScreenQuad) 
	{
		if(this == pScreenQuad)
		{
			return true;
		}
		pScreenQuad = pScreenQuad->m_pParent;
	}

	return false;
}

void ScreenQuad::SetParent(ScreenQuad* pParent)
{
	if (m_pParent == pParent)
	{
		return;
	}
	
	if(m_pParent)
	{
		RemoveScreenQuadFromParent();
	}
	if(pParent)
	{
		AddScreenQuadToParent(pParent);
	}
	else
	{
		m_pParent = 0;
	}

}


void ScreenQuad::AddScreenQuadToParent(ScreenQuad* pParent)
{
	ASSERT(pParent->m_pFirstChild != this);

	m_pParent = pParent;
	m_pNextSibling = pParent->m_pFirstChild;
	pParent->m_pFirstChild = this;
}


void ScreenQuad::RemoveScreenQuadFromParent()
{
	if (0 == m_pParent)
	{
		return;
	}

	if(this == m_pParent->m_pFirstChild) 
	{
		m_pParent->m_pFirstChild = m_pNextSibling;
		m_pParent = 0;
		return;
	}

	ScreenQuad* pPrev = m_pParent->m_pFirstChild;
	ScreenQuad* pCurr = m_pParent->m_pFirstChild->m_pNextSibling;
	while(0 != pCurr) 
	{
		if(this == pCurr)
		{
			pPrev->m_pNextSibling = pCurr->m_pNextSibling;
			m_pParent = 0;
			return;
		}
		pPrev = pCurr;
		pCurr = pCurr->m_pNextSibling;
	}

	ASSERT(0);		//child not found
}


void ScreenQuad::AttachScreenQuadToParent(ScreenQuad* pParent)
{
	if (m_pParent == pParent)
	{
		return;
	}
	
	// Remove it from the current link if it has one
	if (pParent)
	{
		RemoveScreenQuadFromParent();
	}
	
	m_pParent = pParent;

	// update node hierarchy
	ScreenQuad* pChild = pParent->m_pFirstChild;

	// It's the first child
	if(0 == pChild) 
	{
		m_pNextSibling = pParent->m_pFirstChild;
		pParent->m_pFirstChild = this;
		return;
	}

	// Find the generation's end
	while(pChild->m_pNextSibling)
	{
		pChild = pChild->m_pNextSibling;
	}

	// Link it in
	m_pNextSibling = pChild->m_pNextSibling;
	pChild->m_pNextSibling = this;
}

void ScreenQuad::DeleteAllScreenQuadChildren()
{
	ScreenQuad* pChild = m_pFirstChild;
	while(0 != pChild) 
	{
		ScreenQuad* pChild2 = pChild->m_pNextSibling;
		pChild->Destroy();
		pChild = pChild2;
	}
	m_pFirstChild = 0;
}

void ScreenQuad::Destroy()
{
	DeleteAllScreenQuadChildren();
	SetParent(0);
	delete this;
}

